#include "cardsender_f5g006.h"
#include "plugin.h"

using namespace std;

namespace SwanLink {
namespace Finance {
ICardSenderF5g006Adaptor::ICardSenderF5g006Adaptor()
    : ICardSenderAdaptor(), isOpen(false), handle(nullptr) {
}

ICardSenderF5g006Adaptor::~ICardSenderF5g006Adaptor()
{
    if (!isOpen) {
        return;
    }
    if (handle != nullptr) {
        Close();
    }
}

bool ICardSenderF5g006Adaptor::IsOpen()
{
    if (!isOpen) {
        return false;
    }
    int result = GetStatus();
    if ((result == ERR_DEVICE_NOT_EXIST) || (result == ERR_DEVICE_DISCONNECT) ||
       (result == ERR_DEVICE_OPEN_FAILED) || (result == ERROR)) {
        return false;
    }
    return true;
}

int ICardSenderF5g006Adaptor::GetStatus()
{
    unsigned char sendBoxStatus = 0;
    unsigned char retainBoxStatus = 0;
    int resultLib = F5G006_GetStatus(handle, &sendBoxStatus, &retainBoxStatus);
    CARDSENDER_HILOGI(CARDSENDER_SRV, "ICardSenderF5g006Adaptor::GetStatus():resultLib %{public}d", resultLib);
    int result = TransformResultCode(resultLib);
    return result;
}

int ICardSenderF5g006Adaptor::Open(const Transport& transport)
{
    int result = ERROR;
    if (isOpen) {
        CARDSENDER_HILOGI(CARDSENDER_SRV, "cardsender f5g006 was already opened");
        result = GetStatus();
        if (result == SUCCESS) {
            return ERR_DEVICE_OPEN_ALREADY;
        }
    }
    if (std::string(transport.dev) == "") {
        return ERR_TRANS_PARAM_ERROR;
    }

    int resultLib = ERROR;
    CARDSENDER_HILOGI(CARDSENDER_SRV, "cardsender f5g006 Open transport dev %{public}s", transport.dev);
    resultLib = F5G006_Connect(transport.dev, &handle);
    CARDSENDER_HILOGI(CARDSENDER_SRV, "F5G006_Connect:%{public}d", resultLib);
    result = TransformResultCode(resultLib);
    if (result == SUCCESS) {
        result = GetStatus();
        if (result == SUCCESS) {
            isOpen = true;
            return result;
        }
    }
    return result;
}

int ICardSenderF5g006Adaptor::TransformResultCode(int code)
{
    int result = ERROR;
    switch (code) {
        case F5G006_E_POWER_DOWN: {
            result = ERR_POWER_DOWN;
            break;
        }
        case F5G006_E_SUPPLY_BIN_EMPTY: {
            result = ERR_SUPPLY_BIN_EMPTY;
            break;
        }
        case F5G006_E_NO_SUPPLY_BIN: {
            result = ERR_NO_SUPPLY_BIN;
            break;
        }
        case F5G006_E_HARDWARE_ERROR: {
            result = ERR_HARDWARE_ERROR;
            break;
        }
        case F5G006_E_NO_RETAIN_BIN: {
            result = ERR_NO_RETAIN_BIN;
            break;
        }
        case F5G006_E_RETAIN_BIN_FULL: {
            result = ERR_RETAIN_BIN_FULL;
            break;
        }
        case F5G006_NO_ERROR: {
            result = SUCCESS;
            break;
        }
        case F5G006_E_TIMEOUT: {
            result = TIMEOUT;
            break;
        }
        case F5G006_E_INVALID_PARAM: {
            result = ERR_TRANS_PARAM_ERROR;
            break;
        }
        case F5G006_E_DEV_NOT_FOUND: {
            result = ERR_DEVICE_NOT_EXIST;
            break;
        }
        case F5G006_E_CONN_LOST: {
            result = ERR_DEVICE_DISCONNECT;
            break;
        }
        case F5G006_E_ACCESS: {
            result = ERR_DEVICE_OPEN_FAILED;
            break;
        }
        case F5G006_E_INVALID_HANDLE: {
            result = ERROR;
            break;
        }
        case F5G006_E_NO_ACK: {
            result = ERR_DEVICE_NOT_EXIST;
            break;
        }
        default: {
            result = ERROR;
        }
    }
    return result;
}

int ICardSenderF5g006Adaptor::Close()
{
    if (!isOpen) {
        CARDSENDER_HILOGI(CARDSENDER_SRV, "cardsender f5g006 was not opened");
        return ERR_DEVICE_NOT_OPEN;
    }
    int resultLib = ERROR;
    int result = ERROR;
    result = GetStatus();
    if ((result == ERR_DEVICE_NOT_EXIST) || (result == ERR_DEVICE_DISCONNECT) ||
       (result == ERR_DEVICE_OPEN_FAILED) || (result == ERROR)) {
        return ERR_DEVICE_DISCONNECT;
    }
    resultLib = F5G006_Disconnect(handle);
    CARDSENDER_HILOGI(CARDSENDER_SRV, "F5G006_Connect:%{public}d", resultLib);
    result = TransformResultCode(resultLib);
    if (SUCCESS == result) {
        isOpen = false;
    }
    return result;
}

int ICardSenderF5g006Adaptor::Reset()
{
    if (!isOpen) {
        CARDSENDER_HILOGI(CARDSENDER_SRV, "cardsender f5g006 was not opened");
        return ERR_DEVICE_NOT_OPEN;
    }
    int result = ERROR;
    result = GetStatus();
    if ((result == ERR_DEVICE_NOT_EXIST) || (result == ERR_DEVICE_DISCONNECT) ||
       (result == ERR_DEVICE_OPEN_FAILED) || (result == ERROR)) {
        return ERR_DEVICE_DISCONNECT;
    }
    return SUCCESS;
}

int ICardSenderF5g006Adaptor::GetStatus(unsigned char pSuppBinStat[], unsigned char pRetainBinStat[])
{
    if (!isOpen) {
        CARDSENDER_HILOGI(CARDSENDER_SRV, "cardsender f5g006 was not opened");
        return ERR_DEVICE_NOT_OPEN;
    }
    int resultLib = ERROR;
    int result = ERROR;
    resultLib = F5G006_GetStatus(handle, pSuppBinStat, pRetainBinStat);
    CARDSENDER_HILOGI(CARDSENDER_SRV, "F5G006_GetStatus:resultLib %{public}d", resultLib);
    result = TransformResultCode(resultLib);
    CARDSENDER_HILOGI(CARDSENDER_SRV, "F5G006_GetStatus:result %{public}d", result);
    if ((result == ERR_DEVICE_NOT_EXIST) || (result == ERR_DEVICE_DISCONNECT) ||
       (result == ERR_DEVICE_OPEN_FAILED) || (result == ERROR)) {
        return ERR_DEVICE_DISCONNECT;
    }
    return result;
}

int ICardSenderF5g006Adaptor::DispenseCard()
{
    if (!isOpen) {
        CARDSENDER_HILOGI(CARDSENDER_SRV, "cardsender f5g006 was not opened");
        return ERR_DEVICE_NOT_OPEN;
    }
    int resultLib = ERROR;
    int result = ERROR;
    result = GetStatus();
    if ((result == ERR_DEVICE_NOT_EXIST) || (result == ERR_DEVICE_DISCONNECT) ||
       (result == ERR_DEVICE_OPEN_FAILED) || (result == ERROR)) {
        return ERR_DEVICE_DISCONNECT;
    }
    resultLib = F5G006_Dispense(handle);
    CARDSENDER_HILOGI(CARDSENDER_SRV, "DispenseCard:%{public}d", resultLib);
    result = TransformResultCode(resultLib);
    return result;
}

int ICardSenderF5g006Adaptor::GetStatus(char* err)
{
    // 发卡机不使用该函数
    return SUCCESS;
}
}  // namespace Finance
}  // namespace SwanLink

std::shared_ptr<SwanLink::Finance::IAdaptor> CreateAdaptor()
{
    return std::static_pointer_cast<SwanLink::Finance::IAdaptor>(
        std::make_shared<SwanLink::Finance::ICardSenderF5g006Adaptor>());
}


SwanLink::Finance::Transport GetAccess(SwanLink::Finance::ACCESS_MODE mode, const char* dev)
{
    SwanLink::Finance::Transport trans;
    if (mode == SwanLink::Finance::AM_SERIAL) {
        SwanLink::Finance::SerialTransport serialTran;
        serialTran.mode = mode;
        strcpy_s(serialTran.dev, MAX_DEV_NAME_LEN, dev);
        serialTran.timeout = 5000;
        serialTran.baudrate = 115200;
        trans = serialTran;
    } else {
        SwanLink::Finance::UsbTransport usbTran;
        usbTran.mode = mode;
        strcpy_s(usbTran.dev, MAX_DEV_NAME_LEN, dev);
        usbTran.bus_num = 0;
        usbTran.dev_num = 0;
        trans = usbTran;
    }
    return trans;
}

static Plugin g_plugin = {
    .CreateAdaptor = CreateAdaptor,
    .GetAccess = GetAccess,
    .version = "1.0",
    .name = "CardSender_f5g006",
    .desc = "cardsender f5g006 Adaptor"
};

PLUGIN_INIT(&g_plugin);
